// 使用 D8 内置的 readbuffer 函数读取 Wasm 文件
const buffer = readbuffer("/home/sjk/桌面/asc_test/build/test4.wasm");

// 手动实现 TextEncoder 和 TextDecoder
function TextEncoder() {}

TextEncoder.prototype.encode = function(str) {
    const encoder = new Uint8Array(str.length);
    for (let i = 0; i < str.length; i++) {
        encoder[i] = str.charCodeAt(i);
    }
    return encoder;
};

function TextDecoder() {}

TextDecoder.prototype.decode = function(buffer) {
    let str = '';
    for (let i = 0; i < buffer.length; i++) {
        str += String.fromCharCode(buffer[i]);
    }
    return str;
};

const encoder = new TextEncoder();
const decoder = new TextDecoder();

// 定义初始化和调用 WebAssembly 模块的函数
async function instantiateWasm(buffer) {
    const importObject = {
        env: {
            abort: function (message, fileName, lineNumber, columnNumber) {
                throw new Error(`${message} in ${fileName}:${lineNumber}:${columnNumber}`);
            }
        }
    };

    const module = await WebAssembly.compile(buffer);
    const instance = await WebAssembly.instantiate(module, importObject);

    const memory = instance.exports.memory;
    const dataview = new DataView(memory.buffer);
    // 获取最新的 DataView 对象
    function getDataView() {
        return new DataView(memory.buffer);
    }

    // 将数组转为 WebAssembly 线性内存格式
    function lowerArray(values) {
        const start = performance.now();
        const length = values.length;
        const maxNameLength = 256; // 假设最长名字长度为 256
        const bytesPerStudent = 48 + maxNameLength; // 每个 Student 占用的总字节数
        const totalBytes = length * bytesPerStudent;
        const pointer = instance.exports.__pin(instance.exports.__new(totalBytes, 1)); // 分配足够的内存
        const dataview = getDataView();

        for (let i = 0; i < length; i++) {
            const offset = pointer + (i * bytesPerStudent);
            const student = values[i];
            const nameLength = student.name.length;
            const nameOffset = offset + 48; // 名字偏移量
            const nameBuffer = encoder.encode(student.name);

            dataview.setUint32(offset, nameLength, true); // 名字长度
            dataview.setUint32(offset + 4, student.age, true); // 年龄
            dataview.setUint32(offset + 8, nameOffset, true); // 名字偏移量
            dataview.setFloat64(offset + 16, student.mathGrade, true); // 数学成绩
            dataview.setFloat64(offset + 24, student.englishGrade, true); // 英语成绩
            dataview.setFloat64(offset + 32, student.scienceGrade, true); // 科学成绩

            for (let j = 0; j < nameLength; j++) {
                dataview.setUint8(nameOffset + j, nameBuffer[j]);
            }
        }

        instance.exports.__unpin(pointer);
        const end = performance.now();
        return { pointer, time: end - start };
    }

    // 从 WebAssembly 线性内存中提取数组
    function liftArray(pointer, length) {
        const start = performance.now();
        const dataview = getDataView();
        const result = [];
        const maxNameLength = 256; // 假设最长名字长度为 256
        const bytesPerStudent = 48 + maxNameLength; // 每个 Student 占用的总字节数

        for (let i = 0; i < length; i++) {
            const offset = pointer + (i * bytesPerStudent);
            const nameLength = dataview.getUint32(offset, true);
            const age = dataview.getUint32(offset + 4, true);
            const nameOffset = dataview.getUint32(offset + 8, true);
            const nameBuffer = new Uint8Array(nameLength);

            for (let j = 0; j < nameLength; j++) {
                nameBuffer[j] = dataview.getUint8(nameOffset + j);
            }

            const name = decoder.decode(nameBuffer);
            const mathGrade = dataview.getFloat64(offset + 16, true);
            const englishGrade = dataview.getFloat64(offset + 24, true);
            const scienceGrade = dataview.getFloat64(offset + 32, true);
            result.push({ name, age, studentId: `ID${i}`, mathGrade, englishGrade, scienceGrade });
        }

        const end = performance.now();
        return { result, time: end - start };
    }

    return {
        baselineTestStudents: () => {
            instance.exports.baselineTestStudents();
            return { lowerTime: 0, liftTime: 0 };
        },
        noInputWithOutputStudents: () => {
            const resultPointer = instance.exports.noInputWithOutputStudents();
            const { result, time: liftTime } = liftArray(resultPointer, 1000);
            return { result, lowerTime: 0, liftTime };
        },
        withInputAndOutputStudents: (students) => {
            const { pointer, time: lowerTime } = lowerArray(students);
            const resultPointer = instance.exports.withInputAndOutputStudents(pointer);
            const { result, time: liftTime } = liftArray(resultPointer, 1000);
            return { result, lowerTime, liftTime };
        },
        withInputNoOutputStudents: (students) => {
            const { pointer, time: lowerTime } = lowerArray(students);
            instance.exports.withInputNoOutputStudents(pointer);
            return { lowerTime, liftTime: 0 };
        }
    };
}

// 测试代码
async function test() {
    try {
        const wasmFunctions = await instantiateWasm(buffer);

        const inputStudents = new Array(1000).fill(0).map((_, i) => ({
            name: `Student${i}`,
            age: 20,
            studentId: `ID${i}`,
            mathGrade: 85.0,
            englishGrade: 90.0,
            scienceGrade: 88.0
        }));
        const iterations = 10;

        // 辅助函数：执行测试并记录时间
        function runTest(name, testFunction) {
            const start = performance.now();
            let totalLowerTime = 0;
            let totalLiftTime = 0;

            for (let i = 0; i < iterations; i++) {
                const result = testFunction();
                totalLowerTime += result.lowerTime;
                totalLiftTime += result.liftTime;
            }

            const end = performance.now();

            print(`${name}: ${end - start}ms`);
            if (totalLowerTime > 0) {
                print(`  LowerArray Time: ${totalLowerTime}ms`);
            }
            if (totalLiftTime > 0) {
                print(`  LiftArray Time: ${totalLiftTime}ms`);
            }
        }

        // Baseline Test
        //runTest('Baseline Test Students', wasmFunctions.baselineTestStudents);

        // No Input, With Output
        //runTest('No Input, With Output Students', wasmFunctions.noInputWithOutputStudents);

        // With Input, With Output
        //runTest('With Input, With Output Students', () => wasmFunctions.withInputAndOutputStudents(inputStudents));

        // With Input, No Output
        runTest('With Input, No Output Students', () => wasmFunctions.withInputNoOutputStudents(inputStudents));
    } catch (error) {
        print(`Error: ${error.message}`);
    }
}

// 运行测试
test().catch((err) => print(`Error: ${err}`));